package org.weasel.controllers;


import java.util.ArrayList;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IPageLayout;
import org.weasel.base.Activator;
import org.weasel.base.Perspective;
import org.weasel.business.Project;
import org.weasel.models.ChangeListener;
import org.weasel.models.Model;
import org.weasel.tree.TreeObjectIteration;
import org.weasel.tree.TreeObjectProject;
import org.weasel.tree.TreeObjectRelease;
import org.weasel.tree.TreeObjectUserStory;
import org.weasel.views.DeveloperView;

@SuppressWarnings("unused")
public class ApplicationController {
	private static ApplicationController instance = null;
	private ArrayList<ChangeListener> changeListeners = null;
	private TreeController treeController;
	private UserStoryViewController userStoryViewController;
	private ProjectViewController projectViewController;
	private ReleaseViewController releaseViewController;
	private IterationViewController iterationViewController;
	private DeveloperViewController developerViewController;
	private IterationChartController iterationChartController;
	private PreferenceController preferenceController;
	private Model model;
	
	private ApplicationController(){
		changeListeners = new ArrayList<ChangeListener>();
		try {
			model = new Model();
			model.load();
			
			preferenceController = PreferenceController.instance();
			preferenceController.setAppController(this);
			
			treeController = TreeController.instance();
			treeController.setApplicationController(this);
			
			developerViewController = DeveloperViewController.instance();
			developerViewController.setApplicationController(this);
			developerViewController.setModel(model);
			
			userStoryViewController = UserStoryViewController.instance();
			userStoryViewController.setApplicationController(this);
			
			projectViewController = ProjectViewController.instance();
			projectViewController.setApplicationController(this);
			
			releaseViewController = ReleaseViewController.instance();
			releaseViewController.setApplicationController(this);
			
			iterationViewController = IterationViewController.instance();
			iterationViewController.setApplicationController(this);
			
			//iterationChartController = new IterationChartController();
			//iterationChartController.setApplicationController(this);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static ApplicationController instance(){
		if (instance == null)
			instance = new ApplicationController();
		return instance;
	}
	
	public void registerListener(ChangeListener listener){
		this.changeListeners.add(listener);
	}
	
	public void unregisterListener(ChangeListener listener){
		this.changeListeners.remove(listener);
	}
	
	public boolean programCloseClicked() {
		treeController.getNavigator().setFocus();
		if(treeController.existUnsavedChanges()) {
			Shell shell = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell();
			MessageBox messageBox = new MessageBox(shell, SWT.YES | SWT.NO | SWT.CANCEL | SWT.ICON_QUESTION);
			messageBox.setText("Close program");
			messageBox.setMessage("Do You want to save changes?");
			int result = messageBox.open();
			if(result == SWT.YES) {
				//yes button clicked -> windows is closed and changes are saved
				model.save();
				return true;
			} else if(result == SWT.NO) {
				//no button clicked -> window is closed without saving
				return true;
			} else {
				//cancel button clicked -> window remains open
				return false;
			}
		} else {
			//if there are no unsaved changes -> the window is closed
			return true;
		}
	}
	
	public void changesOccured() {
		treeController.enableSaveButton();
//		notify listeners
		notifyChangeListeners();
	}

	private void notifyChangeListeners() {
		for (ChangeListener listener : changeListeners) {
			listener.changeHappened();
		}
	}
		
	public void saveModel() {
		model.save();
		treeController.disableSaveButton();
	}
	
	/**
	 * For loading the model out of a new XML file whose path
	 * is retrieved from the PreferenceStore
	 */
	public void loadModel() {
		model.load();
	}
	
	public Model getModel() {
		return model;
	}
	
	public TreeController getTreeController() {
		return treeController;
	}

	public void updateViews(){
		projectViewController.updateProjectViews();
		userStoryViewController.updateStoryViews();
		releaseViewController.updateReleaseViews();
		iterationViewController.updateIterationViews();
		developerViewController.refreshViewer();
		treeController.refreshViewer();
	}
	
	/**
	 * Sets the developer-view
	 *
	 */
	public void showDeveloperView(){
		IPageLayout layout = Perspective.actualLayout;
		layout.addView(DeveloperView.ID, IPageLayout.BOTTOM, 0.75f, layout.getEditorArea());
	}
	
	/**
	 * Here a TreeObjectUserStory is passed, since also the name of the associated
	 * TreeObject has to be updated when the user-story name changes
	 * @param to_story
	 * @param project TODO
	 */
	public void showUserStoryView(TreeObjectUserStory to_story, Project project){
		userStoryViewController.setUserStory(to_story);
		userStoryViewController.setProjectOfUserStory(project);
		userStoryViewController.showUserStoryView();
	}
	
	public void showProjectView(TreeObjectProject to_project) {
		projectViewController.setTo_project(to_project);
		projectViewController.setComp(model.getCompany());
		projectViewController.showProjectView();
	}
	
	public void showReleaseView(TreeObjectRelease to_release) {
		releaseViewController.setTo_release(to_release);
		releaseViewController.showReleaseView();
	}
	
	public void showIterationView(TreeObjectIteration to_iteration) {
		iterationViewController.setTo_iteration(to_iteration);
		iterationViewController.showIterationView();
	}
	
	/**
	 * can be called from any controller attached to this one! For instance
	 * the UserStoryViewController needs this method in order to update the UserStory
	 * name in the TreeObject when it is changed
	 *
	 */
	public void refreshTreeViewer(){
		treeController.refreshViewer();
	}

	/**
	 * calculates the start-end dates of Project, Release and Iterations
	 * The computation is done only on the model and not saved to the
	 * XML file except for the start-date of the Project
	 *
	 */
	public void calculateDates() {
		model.calculateDates();
	}

}
